package com.itfreer.bpm.activiti.modeldeploy;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import com.itfreer.bpm.model.api.EDeployType;
import com.itfreer.bpm.model.dao.IModelDeployDao;
import com.itfreer.bpm.option.para.TaskInfo;
import com.itfreer.bpm.option.para.TaskType;
import com.itfreer.bpm.rootpath.BpmRootPathPara;


/**
 * 流程发布类
 * @author gj
 *
 */
@Component("activitiModelDeployDao")
public class ActivitiModelDeployDao implements  IModelDeployDao{
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private BpmRootPathPara bpmRootPath;
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	/**
	 * 发布模型
	 */
	@Override
	public EDeployType deployModel(String key) {
		EDeployType result=EDeployType.DeploySuccess;
		
		//读取部署文件
		String filename=getBpmFileName(bpmRootPath.getRootPath(),key);
		
		String message="";
		if(filename==null) {
			message="流程文件："+key+"在文件目录"+bpmRootPath.getRootPath()+"下没有找到";
			logger.debug(message);
			result=EDeployType.Failed;
		}
		boolean doDeploy = true;
		Resource fileRource = new FileSystemResource(filename);
		String deploymentName = fileRource.getFilename();
		if(deploymentName!=null) {
			deploymentName=deploymentName.replace(".bpmn", "");
		}
		String resourceName = fileRource.getFilename();
		
		try{
			List<Deployment> deployments = repositoryService
					.createDeploymentQuery().deploymentName(deploymentName)
					.orderByDeploymenTime().desc().list();
			//判断是否已经发布服务,如果已经发布，判断服务是否变化
			if (!deployments.isEmpty()) {
				Deployment existing = deployments.get(0);
				InputStream in = repositoryService.getResourceAsStream(
						existing.getId(), resourceName);
				if (in != null) {
					File f = File.createTempFile("deployment", "xml",
							new File(System.getProperty("java.io.tmpdir")));
					f.deleteOnExit();
					OutputStream out = new FileOutputStream(f);
					IOUtils.copy(in, out);
					in.close();
					out.close();
					doDeploy = (FileUtils.checksumCRC32(f) != FileUtils
							.checksumCRC32(fileRource.getFile()));
					
					//如果已经发布，且服务没有变化，直接告知服务无需重新发布
					if(!doDeploy) {
						result=EDeployType.Deployed;
					}else {
						result=EDeployType.RDeploySuccess;
					}
				} else {
					System.out.println("不能读取资源 " + resourceName + ", 输入流为空");
					result=EDeployType.RDeployFailed;
				}
			}
			
			if (doDeploy) {
				repositoryService.createDeployment().name(deploymentName)
						.addInputStream(resourceName, fileRource.getInputStream())
						.deploy();
				
				message="文件部署成功 : " + fileRource.getFilename();
			}
		}catch(Exception ex){
			//文件服务发布和部署
			message="文件【"+resourceName+"】部署失败，原因 : " + ex.getMessage();
			logger.debug(message);
			result=EDeployType.Failed;
		}
		
	    return result;
	}
	
	/**
	 * 获取工作流文件
	 * @param path
	 * @param name
	 * @return
	 */
	private static String getBpmFileName(String path, String name) {
		File file = new File(path);
		System.out.println("工作流文件路径为："+path);
		
		String fullname=null;
		if (file.isDirectory()) {
			File[] dirFile = file.listFiles();
			for (File f : dirFile) {
				if (f.isDirectory())
					fullname=getBpmFileName(f.getAbsolutePath(), name);
					if((name+".bpmn").equals(fullname)) {
						return fullname;
					}
				else {
					if (f.getName().equals(name+".bpmn")){
						fullname= f.getAbsolutePath();
						return fullname;
					}
				}
			}
		}else{
			if (file.getName().endsWith(".bpmn")){
				fullname= file.getAbsolutePath();
				return fullname;
			}
		}
		return fullname;
	}


	/**
	 * 获取流程节点信息
	 */
	@Override
	public List<TaskInfo> getProcessTask(String key) {
		ProcessDefinition processDefinition = repositoryService
				.createProcessDefinitionQuery()
				.processDefinitionKey(key).latestVersion()
				.singleResult();
		List<TaskInfo> tasks=new ArrayList<TaskInfo>();
        BpmnModel model = repositoryService.getBpmnModel(processDefinition.getId());
        if(model!=null) {
        	Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
            for(FlowElement e : flowElements) {
                System.out.println("flowelement id:" + e.getId() + "  name:" + e.getName() + "   class:" + e.getClass().toString());
                
                if(e.getClass().toString().trim().toLowerCase().endsWith("org.activiti.bpmn.model.usertask")) {
                	UserTask task=(UserTask)e;
                	String assigness=task.getAssignee();
                	TaskInfo taskinfo=new TaskInfo();
                	taskinfo.setTaskdefinedid(e.getId());
                	taskinfo.setTaskName(e.getName());
                	if(assigness==null || "".equals(assigness.trim()) || !"${countersigner}".equals(assigness)) {
                		taskinfo.setTaskType(TaskType.CommonTask);
                	}else{
                		taskinfo.setTaskType(TaskType.MultiTask);
                	}
                 	tasks.add(taskinfo);
                }
               
            }
        }
		return tasks;
	}


	/**
	 * 通过流程id获取流程名称
	 */
	@Override
	public String getProcessName(String key) {
		ProcessDefinition processDefinition = repositoryService
				.createProcessDefinitionQuery()
				.processDefinitionKey(key).latestVersion()
				.singleResult();
		return processDefinition.getName();
	}
}
